SpringBoot ClassPathResource获取文件(包含一个坑,两个知识点) 您所在的位置:网站首页 Maven jar包找不到 SpringBoot ClassPathResource获取文件(包含一个坑,两个知识点)

SpringBoot ClassPathResource获取文件(包含一个坑,两个知识点)

#SpringBoot ClassPathResource获取文件(包含一个坑,两个知识点)| 来源: 网络整理| 查看: 265

问题

SpringBoot项目,在Idea中无论怎么运行,都是正常的,通过maven打包的jar包运行时,ClassPathResource#getFile()方法,始终报错,找不到文件。 代码如下:配置Freemarker的模板路径 在这里插入图片描述 报错如下:不论是文件还是文件夹,都会报错

13:52:12.405 ERROR [main] com.edu.compile.parse.FreemarkerParse:35 - freemarker init failed: class path resource [template/ftl/] cannot be resolved to absolute file path because it does not reside in the file system: jar:file:/E:/dev_file/git/lowcode/target/lowcode-1.0.jar!/BOOT-INF/classes!/template/ftl/ 13:52:12.424 INFO [main] com.edu.control.config.RetryQueueStarter:95 - init retry task delay queue ... 13:52:13.613 INFO [main] o.s.s.concurrent.ThreadPoolTaskExecutor:171 - Initializing ExecutorService 13:52:13.614 INFO [main] o.s.s.concurrent.ThreadPoolTaskExecutor:171 - Initializing ExecutorService 'deployThreadPool' Logging initialized using 'class org.apache.ibatis.logging.stdout.StdOutImpl' adapter. Parsed mapper file: 'class path resource [mapper/EventDefineMapper.xml]' Parsed mapper file: 'class path resource [mapper/EventNodeMapper.xml]' Parsed mapper file: 'class path resource [mapper/EventVersionMapper.xml]' 13:52:14.736 INFO [main] com.edu.compile.util.LocalNodeEnv:77 - start init Windows 10 node env 13:52:14.736 INFO [main] com.edu.compile.util.LocalNodeEnv:83 - node uncompressed status: false 13:52:14.739 ERROR [main] com.edu.compile.util.LocalNodeEnv:165 - node check error: Cannot run program "file:\E:\dev_file\git\lowcode\target\lowcode-1.0.jar!\BOOT-INF\classes!\node-win-x64/bin/node.exe": CreateProcess error 网上的解决方案(对我来说不靠谱)

网上提供了几种解决方案,我只记住了两种: 第一种是ResourceUtils.getFile(),网上说linux下不通用,实际情况也会报相同的错误。 第二种是FreemarkerParse.class.getClassLoader().getResourceAsStream("");通过读取流的方式,网上说这是一种通用的方式,确实是通用的方式,但是获取一个文件夹怎么弄?我的需求是获取当前的路径,而不是当前的文件。

问题分析

从报错信息来看jar:file:/E:/dev_file...很明显,是从jar文件中找东西的,握草,对于使用SpringBoot不熟悉的小伙伴(我™在说我自己,毕太久没有用过它了),先从打包插件和打的包来看,SpringBoot package仅仅只有一个jar文件,在jar文件中,包含了执行依赖,并且MANIFEST.MF也是SpringBoot重新定义了ClassPath(忘了原始的是什么样子了?下面有)。 启动命令:java -jar xxx.jar 好好想一想,这个命令启动SpringBoot项目,涉及了几个classpath? 至少涉及了两个classpath,一个是JVM的classpath,也就是我们常说的classpath,另一个是SpringBoot定义的classpath。

插件:

org.springframework.boot spring-boot-maven-plugin ${spring.boot.version} com.edu.Application repackage

jar: 在这里插入图片描述

解决方案 解决思路

既然SpringBoot定义了一个classpath,那我偏偏不用SpringBoot提供的,我非要自定义classpath和打包文件。

将SpringBoot打的Jar和配置文件分离修改jar中的MANIFEST.MF修改为通用的内容将jar和配置文件打成tar.gz包,用于部署 盘他 spring-boot-maven-plugin(我不会用)

我说了SpringBoot,我用的不熟,可能这个插件或者其他springboot的插件有提供功能,但是我不知道,也不会用

resources、dependency、jar、assembly

我会用这四个插件解决问题

resources

将/src/main/resources下的所有文件,拷贝到target下的conf文件夹下

maven-resources-plugin 3.0.2 copy-resources validate copy-resources ${project.build.directory}/conf /src/main/resources false

dependency

将项目依赖的jar拷贝到target下的lib文件夹

maven-dependency-plugin copy package copy-dependencies ${project.build.directory}/lib

以上两个插件生成的效果图: 在这里插入图片描述

jar

打包jar包,定义MANIFEST.MF文件,设置依赖的jar的路径和配置文件的路径,其实相当于重新定义了classpath。 注意:conf前有两个点,依赖jar的前缀有一个点(可以不填前缀),这两个东西和第四个插件相呼应。

maven-jar-plugin **/*.class ${main.class} true false ./ ../conf/

生成的MANIFEST.MF: 在这里插入图片描述

assembly 这个是最复杂的插件,包含了一个子文件assembly.xml,这个插件是将上面生成的conf、lib、jar打成tar.gz压缩包。 在assembly.xml中,引用了上面插件生成的conf、lib的文件路径,该插件会将打好的jar放入lib中,将conf、lib打成tar.gz压缩包。上面说conf前有两个点,你明白了吗?因为jar最终会被放入lib中,所以必须在conf前加上两个点,表示上级目录的文件夹。

org.apache.maven.plugins maven-assembly-plugin 3.1.0 ${project.artifactId} false /src/main/resources/assembly/assembly.xml assembly package single

assembly.xml

assembly tar.gz false ${project.build.directory}/conf conf true **/*.xml **/*.properties ${project.build.directory}/conf conf false **/*.xml **/*.properties ${project.build.directory}/lib lib false lib

在这里插入图片描述 效果图: 在这里插入图片描述

jar、assembly(终极解决方案)

上面使用了四个插件,太™多了,仅用jar、assembly插件就可以搞定! 两个插件的配置基本不变,改变的仅仅是assembly的子文件assembly.xml, 修改的内容是${project.build.directory}/conf替换为src/main/resources。

maven-jar-plugin **/*.class ${main.class} true false ../conf/ org.apache.maven.plugins maven-assembly-plugin 3.1.0 ${project.artifactId} false /src/main/resources/assembly/assembly.xml assembly package single assembly tar.gz false src/main/resources conf true **/*.xml **/*.properties src/main/resources conf false **/*.xml **/*.properties lib 总结

通过自定义classpath,可以让springboot中的Resource#getFile()表现出正确的行为。

SpringBoot中获取ClassPath下的文件引出当前博客

知识点 Resource#getFile()在SpringBoot中存在的问题四个插件的含义和使用


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有